﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoCAD.EntityTools
{
    public static class CurveTools
    {
        /// <summary>
        /// 安全获取曲线对象（全面检查对象有效性）
        /// </summary>
        /// <param name="curve">要检查的曲线对象</param>
        /// <param name="tr">当前事务</param>
        /// <returns>有效的曲线对象或null</returns>
        public static Curve GetValidCurve(this Transaction tr, Curve curve)
        {
            // 前置条件检查
            if (curve == null || tr == null || tr.IsDisposed)
                return null;

            try
            {
                // 获取对象ID
                ObjectId id = curve.ObjectId;

                // 全面检查对象ID状态
                if (id.IsNull || id.IsErased || !id.IsValid)
                    return null;

                // 检查对象类型是否为曲线或其派生类
                if (!id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Curve))))
                    return null;

                // 安全获取对象（不打开已删除对象，允许打开锁定图层上的对象）
                DBObject dbObj = tr.GetObject(id, OpenMode.ForRead, false, true);

                // 检查获取的对象状态
                if (dbObj == null || dbObj.IsDisposed || dbObj.IsErased)
                    return null;

                // 返回转换后的曲线对象
                return dbObj as Curve;
            }
            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                // 记录AutoCAD特定异常
                ($"AutoCAD异常获取曲线对象: {ex.ErrorStatus}").CadMessage2();
                return null;
            }
            catch (System.Exception ex)
            {
                // 记录通用异常
                ($"系统异常获取曲线对象: {ex.Message}").CadMessage2(); ;
                return null;
            }
        }

        /// <summary>
        /// 尝试获取有效的曲线对象
        /// </summary>
        public static Curve TryGetValidCurve(this Curve curve, Transaction tr)
        {
            try
            {
                // 基础检查
                if (curve == null || tr == null || tr.IsDisposed)
                    return null;

                ObjectId id = curve.ObjectId;

                // 检查对象ID状态
                if (id.IsNull || id.IsErased || !id.IsValid)
                    return null;

                // 安全获取对象
                DBObject dbObj = tr.GetObject(id, OpenMode.ForRead, false, true);

                // 检查对象状态
                if (dbObj == null || dbObj.IsDisposed || dbObj.IsErased)
                    return null;

                // 转换为Curve并确保可写
                if (dbObj is Curve curveObj)
                {
                    if (!curveObj.IsWriteEnabled)
                    {
                        curveObj.UpgradeOpen();
                    }

                    // 最终状态验证
                    if (curveObj.IsWriteEnabled && !curveObj.IsErased && !curveObj.IsDisposed)
                    {
                        return curveObj;
                    }
                }
            }
            catch (System.InvalidOperationException)
            {
                // 专门捕获无效操作异常
                return null;
            }
            catch (Autodesk.AutoCAD.Runtime.Exception)
            {
                // 捕获AutoCAD特定异常
                return null;
            }

            return null;
        }

        ///// <summary>
        ///// 曲线长度
        ///// </summary>
        ///// <param name="curve">曲线</param>
        ///// <returns>长度</returns>
        //public static double GetLength(this Curve curve)
        //{
        //    return curve.GetDistanceAtParameter(curve.EndParam);
        //}

        /// <summary>
        /// 安全地计算曲线长度（解决 eInvalidOpenState 异常）
        /// </summary>
        /// <param name="curve">曲线对象</param>
        /// <returns>曲线长度</returns>
        public static double GetLength(this Curve curve)
        {
            if (curve == null)
                throw new ArgumentNullException(nameof(curve));

            try
            {
                // 直接获取长度，不需要检查或改变打开状态
                return curve.GetDistanceAtParameter(curve.EndParam);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("计算曲线长度时发生错误", ex);
            }
        }

        /// <summary>
        /// 安全获取曲线长度（带事务处理）
        /// </summary>
        public static double GetLengthSafe(this Curve curve, Transaction trans = null)
        {
            if (curve == null)
                throw new ArgumentNullException(nameof(curve));

            bool shouldCloseTransaction = false;

            try
            {
                // 如果没有传入事务，自己创建一个
                if (trans == null)
                {
                    trans = curve.Database.TransactionManager.StartTransaction();
                    shouldCloseTransaction = true;
                }

                // 确保曲线对象在事务中以读方式打开
                if (!curve.ObjectId.IsValid || curve.ObjectId.IsErased)
                    throw new InvalidOperationException("曲线对象无效或已被删除");

                // 直接返回长度
                return curve.GetDistanceAtParameter(curve.EndParam);
            }
            finally
            {
                // 如果是自己创建的事务，需要关闭
                if (shouldCloseTransaction && trans != null)
                {
                    trans.Commit();
                    trans.Dispose();
                }
            }
        }

        /// <summary>
        /// 安全获取曲线长度（不抛出异常）
        /// </summary>
        public static bool TryGetLength(this Curve curve, out double length, Transaction trans = null)
        {
            length = 0;

            if (curve == null)
                return false;

            try
            {
                length = curve.GetLengthSafe(trans);
                return true;
            }
            catch
            {
                return false;
            }
        }
        ///// <summary>
        ///// 复制曲线通用属性
        ///// </summary>
        //public static void CopyCommonCurveProperties(this Curve source, Curve target)
        //{
        //    target.Layer = source.Layer;
        //    target.Color = source.Color;
        //    target.Linetype = source.Linetype;
        //    target.LinetypeScale = source.LinetypeScale;
        //    target.LineWeight = source.LineWeight;
        //    target.Visible = source.Visible;
        //    target.Transparency = source.Transparency;

        //    // 复制扩展数据（如果有）
        //    if (source.XData != null)
        //    {
        //        target.XData = source.XData;
        //    }
        //}

        [Obsolete("待优化")]
        /// <summary>
        /// 复制曲线通用属性
        /// </summary>
        /// <summary>
        /// 安全的属性复制方法（不处理事务）
        /// </summary>
        public static void CopyCommonCurvePropertiesSafe(this Curve source, Curve target)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            if (target == null)
                throw new ArgumentNullException(nameof(target));

            // 检查目标实体是否有效且可写
            if (!IsEntityValidForWrite(target))
            {
                throw new InvalidOperationException("目标曲线不可写或无效");
            }

            // 检查源实体是否有效
            if (!IsEntityValidForRead(source))
            {
                throw new InvalidOperationException("源曲线无效");
            }

            try
            {
                // 复制属性
                target.Layer = source.Layer;
                target.Color = source.Color;
                target.Linetype = source.Linetype;
                target.LinetypeScale = source.LinetypeScale;
                target.LineWeight = source.LineWeight;
                target.Visible = source.Visible;

                if (source.Transparency != null)
                {
                    target.Transparency = source.Transparency;
                }

                // 复制XData
                CopyXDataSafe(source, target);
            }
            catch (System.Exception ex)
            {
                throw new InvalidOperationException("复制属性时发生错误", ex);
            }
        }

        /// <summary>
        /// 检查实体是否可读
        /// </summary>
        private static bool IsEntityValidForRead(Entity entity)
        {
            if (entity == null)
                return false;

            try
            {
                // 检查基本属性访问
                var test = entity.Layer;
                return !entity.ObjectId.IsNull && !entity.ObjectId.IsErased;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 检查实体是否可写
        /// </summary>
        private static bool IsEntityValidForWrite(Entity entity)
        {
            if (!IsEntityValidForRead(entity))
                return false;

            try
            {
                // 尝试获取写入权限（不实际修改状态）
                return entity.IsWriteEnabled ||
                       (!entity.ObjectId.IsNull && !entity.ObjectId.IsErased);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 安全的XData复制
        /// </summary>
        private static void CopyXDataSafe(DBObject source, DBObject target)
        {
            try
            {
                if (source.XData != null && target.IsWriteEnabled)
                {
                    ResultBuffer newXData = new ResultBuffer();
                    foreach (TypedValue typedValue in source.XData)
                    {
                        newXData.Add(new TypedValue(typedValue.TypeCode, typedValue.Value));
                    }
                    target.XData = newXData;
                }
            }
            catch
            {
                // 忽略XData复制错误
            }
        }
        /// <summary>
        /// 复制扩展数据（XData）
        /// </summary>
        private static void CopyXData(DBObject source, DBObject target)
        {
            try
            {
                // 清除目标的现有XData
                target.XData = null;

                // 复制源对象的XData
                ResultBuffer sourceXData = source.XData;
                if (sourceXData != null)
                {
                    // 创建新的ResultBuffer来复制数据
                    ResultBuffer newXData = new ResultBuffer();
                    foreach (TypedValue typedValue in sourceXData)
                    {
                        newXData.Add(new TypedValue(typedValue.TypeCode, typedValue.Value));
                    }
                    target.XData = newXData;
                }
            }
            catch (System.Exception ex)
            {
                // 记录错误但继续执行
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\n警告：复制XData时出错: {ex.Message}");
            }
        }

        // 移除有问题的超链接复制代码，或者使用以下替代方案

        /// <summary>
        /// 复制超链接（安全版本）
        /// </summary>
        private static void CopyHyperlinks(Entity source, Entity target)
        {
            try
            {
                // 方法1：尝试使用完全限定名称
                var hyperlinksProperty = source.GetType().GetProperty("Hyperlinks");
                if (hyperlinksProperty != null)
                {
                    dynamic sourceHyperlinks = hyperlinksProperty.GetValue(source);
                    dynamic targetHyperlinks = hyperlinksProperty.GetValue(target);

                    if (sourceHyperlinks != null && targetHyperlinks != null)
                    {
                        targetHyperlinks.Clear();
                        foreach (var hyperlink in sourceHyperlinks)
                        {
                            targetHyperlinks.Add(hyperlink);
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                Application.DocumentManager.MdiActiveDocument?.Editor.WriteMessage(
                    $"\n警告：复制超链接时出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 复制实体通用属性（更通用的方法）
        /// </summary>
        public static void CopyCommonProperties(this Entity source, Entity target)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            if (target == null)
                throw new ArgumentNullException(nameof(target));

            // 检查目标实体是否可写
            if (target.IsWriteEnabled == false)
                target.UpgradeOpen();

            try
            {
                // 复制基本属性
                target.Layer = source.Layer;
                target.Color = source.Color;
                target.Linetype = source.Linetype;
                target.LinetypeScale = source.LinetypeScale;
                target.LineWeight = source.LineWeight;
                target.Visible = source.Visible;

                // 透明度
                if (source.Transparency != null)
                {
                    target.Transparency = source.Transparency;
                }

                // 复制扩展数据
                CopyXData(source, target);

                // 复制超链接
                CopyHyperlinks(source, target);
            }
            finally
            {
                if (target.IsWriteEnabled)
                {
                    target.DowngradeOpen();
                }
            }
        }

    }
}
